package org.barad.architecture.analyzer.model.component;

import java.util.LinkedList;
import java.util.List;

import org.barad.architecture.analyzer.archpad.component.ArchPadComponent;
import org.barad.architecture.analyzer.archpad.component.CloneableEntity;
import org.barad.architecture.analyzer.archpad.component.annotations.ModelProperty;
import org.barad.architecture.analyzer.model.impl.Constraint;
import org.barad.architecture.analyzer.model.impl.Specification;

public abstract class BaseComponent extends ArchPadComponent {
	@ModelProperty
	protected List<Specification> services;
	protected Class<?> servicesContentClass;
	@ModelProperty
	protected List<Specification> dependencies;
	protected Class<?> dependenciesContentClass;
	@ModelProperty
	protected List<Constraint> constraints;
	protected Class<?> constraintsContentClass;
	
	public BaseComponent() {
		this.services = new LinkedList<Specification>();
		this.servicesContentClass = Specification.class;
		this.dependencies = new LinkedList<Specification>();
		this.dependenciesContentClass = Specification.class;
		this.constraints = new LinkedList<Constraint>();
		this.constraintsContentClass = Constraint.class;
	}
	
	@Override
	public Object clone() {
		BaseComponent clone = (BaseComponent)super.clone();
		clone.services = (List<Specification>)cloneList(services);
		clone.servicesContentClass = servicesContentClass;
		clone.dependencies = cloneList(dependencies);
		clone.dependenciesContentClass = dependenciesContentClass;
		clone.constraints = cloneList(constraints);
		clone.constraintsContentClass = constraintsContentClass;
		return clone;
	}
	
	@SuppressWarnings("unchecked")
	protected <T extends CloneableEntity> List<T> cloneList(List<T> list) {
		LinkedList<T> cloneDependency = new LinkedList<T>();
		for (CloneableEntity ce: list) {
			cloneDependency.add((T)ce.clone());
		}
		return cloneDependency; 
	}
	
	public List<Specification> getServices() {
		return services;
	}

	public void setServices(List<Specification> provides) {
		this.services = provides;
	}

	public List<Specification> getDependencies() {
		return dependencies;
	}

	public void setDependencies(List<Specification> requires) {
		this.dependencies = requires;
	}


	public List<Constraint> getConstraints() {
		return constraints;
	}

	public void setConstraints(List<Constraint> constraints) {
		this.constraints = constraints;
	}
	
	public Class<?> getServicesContentClass() {
		return servicesContentClass;
	}

	public void setServicesContentClass(Class<?> providesContentClass) {
		this.servicesContentClass = providesContentClass;
	}

	public Class<?> getDependenciesContentClass() {
		return dependenciesContentClass;
	}

	public void setDependenciesContentClass(Class<?> requiresContentClass) {
		this.dependenciesContentClass = requiresContentClass;
	}


	public Class<?> getConstraintsContentClass() {
		return constraintsContentClass;
	}

	public void setConstraintsContentClass(Class<?> constraintsContentClass) {
		this.constraintsContentClass = constraintsContentClass;
	}
}
